home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / dkbuts.zip / 3D2-DKB.C next >
C/C++ Source or Header  |  1991-05-16  |  22KB  |  877 lines

  1. /*-------------------------------------------------------------------------
  2.  
  3.                3D2 to DKB File Converter
  4.              Copyright 1991 by Steve Anger
  5.  
  6.   This file may be freely modified and distributed so long as the original
  7. copyright notice is included.
  8.  
  9. V1.2 05/09/91 Minor MSC compatibility modifications made by Aaron A. Collins
  10.  
  11. --------------------------------------------------------------------------*/
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <math.h>
  17.  
  18. #ifdef __TURBOC__
  19. #include <alloc.h>
  20. #include <conio.h>
  21. #include <graphics.h>
  22. #endif
  23.  
  24. const char Ver[] = "v1.2";
  25.  
  26. #ifndef M_PI
  27. #define M_PI    3.14159265358979323846
  28. #endif
  29.  
  30. typedef struct
  31. {
  32.     float x, y, z;
  33. } Vector;
  34.  
  35.  
  36. typedef struct
  37. {
  38.     float Red;
  39.     float Green;
  40.     float Blue;
  41. } Palette;
  42.  
  43.  
  44. typedef struct
  45. {
  46.     int    VertA;        /* Vertex A of the triangle */
  47.     int    VertB;        /*   "    B  "  "      "    */
  48.     int    VertC;        /*   "    C  "  "      "    */
  49.     int    Colour;       /* Colour of triangle */
  50.     int    EdgeFlag;     /* Which edges are to be drawn (not used) */
  51. } Triangle;
  52.  
  53.  
  54. typedef struct TriNode
  55. {
  56.     int  TriNo;
  57.     struct TriNode *Next;
  58. } TriangleNode;
  59.  
  60.  
  61. typedef unsigned char byte;
  62. typedef signed int word;
  63. typedef int boolean;
  64. const int true = 1;
  65. const int false = 0;
  66.  
  67. /* Function prototype definitions */
  68. void Read3D2Header(void);
  69. void Read3D2Object(void);
  70.  
  71. void WriteDKBHeader(void);
  72. void WriteDKBObject(void);
  73. void WriteDKBSummary(void);
  74.  
  75. void ProcessArgs (int argc, char *argv[]);
  76. void PrintVector (FILE *g, Vector *V);
  77. void AddExt (char *FileName, char *Ext, boolean Force);
  78. byte ReadByte(FILE *f);
  79. word ReadWord(FILE *f);
  80. void Abort (char* Msg, int ExitCode);
  81. void MinVector (Vector *V1, Vector *V2);
  82. void MaxVector (Vector *V1, Vector *V2);
  83. void VertNormal (Triangle *T, Vector *NormA, Vector *NormB, Vector *NormC);
  84. void BuildTriIndex (void);
  85. void DumpTriIndex (void);
  86. void TriNormal (Triangle *T, Vector *Normal);
  87.  
  88. void InitDisplay(void);
  89. void PlotTriangle (Triangle *Tri);
  90. void CloseDisplay(void);
  91.  
  92. void  VectAdd (Vector *V1, Vector *V2, Vector *V3);
  93. void  VectSub (Vector *V1, Vector *V2, Vector *V3);
  94. void  VectScale (Vector *V1, float k);
  95. float VectMag (Vector *V);
  96. float DotProd (Vector *V1, Vector *V2);
  97. void  CrossProd (Vector *V1, Vector *V2, Vector *V3);
  98. void  VectCopy (Vector *V1, Vector *V2);
  99. void  VectInit (Vector *V, float x, float y, float z);
  100. float VectAngle (Vector *V1, Vector *V2);
  101.  
  102. /* Global variables */
  103. FILE      *f;             /* Input file */
  104. FILE      *g;             /* Output file */
  105. char      InFile[64];     /* Input file name */
  106. char      OutFile[64];    /* Output file name */
  107. boolean   Display;        /* Screen preview flag */
  108. Vector    LookAt;         /* Location to look at */
  109. Vector    ViewPoint;      /* Location of viewpoint */
  110. Vector    Nx, Ny, Nz;     /* Co-ord system for rotated space */
  111. float     Smooth;         /* Smooth triangles who's normals differ by */
  112.               /* less than this angle (degrees) */
  113.  
  114. /* 3D2 Header infomation */
  115. int       ObjCount;       /* Number of objects contained in file */
  116. int       LightOn[3];     /* 1 = Light source is on, 0 = off */
  117. float     LightBright[3]; /* Light source brightness */
  118. Vector    LightPos[3];    /* Light source position */
  119. float     Ambient;        /* Ambient light brightness */
  120. Palette   Pal[16];        /* Colour palette for objects */
  121. int       GBase[16];      /* Colour group base array (not used) */
  122. int       PalType;        /* Colour palette type (not used) */
  123. int       WColour;        /* Wireframe colour (not used) */
  124. int       OColour;        /* Outline colour (not used) */
  125.  
  126. /* 3D2 Object information */
  127. char      ObjName[9];     /* Name of current object */
  128. int       VertCount;      /* Number of verticies in object */
  129. Vector    *Vert;          /* Pointer to array of verticies */
  130. int       TriCount;       /* Number of triangular faces in object */
  131. Triangle  *Tri;           /* Pointer to array of triangles */
  132. int       DegenTri;       /* Degenerate triangles */
  133.  
  134. Vector    ObjMin, ObjMax;
  135. TriangleNode **TriList;   /* List of triangles touching each vertex */
  136.  
  137.  
  138.  
  139. int main (int argc, char* argv[])
  140. {
  141.     int i;
  142.     int  Verticies[40], Triangles[40], Degens[40];
  143.     char Names[40][9];
  144.     int  TotalTri, TotalVert, TotalDegen;
  145.  
  146.     ProcessArgs (argc, argv);
  147.  
  148.     if (Display)
  149.     InitDisplay();
  150.  
  151.     Read3D2Header();                  /* Read 3D2 file header */
  152.     WriteDKBHeader();                 /* Write DKB file header info */
  153.  
  154.     for (i = 0; i < ObjCount; i++) {
  155.     Read3D2Object();              /* Read an object from 3D2 file */
  156.     WriteDKBObject();             /* Write object to DKB file */
  157.  
  158.     strcpy (Names[i], ObjName);   /* Keep a list of the object names, */
  159.     Verticies[i] = VertCount;     /* vertex counts, etc. */
  160.     Triangles[i] = TriCount;
  161.     Degens[i] = DegenTri;
  162.     }
  163.  
  164.     WriteDKBSummary();
  165.  
  166.     fclose(f);
  167.     fclose(g);
  168.  
  169.     if (Display)
  170.     CloseDisplay();
  171.  
  172.     /* Print summary of objects converted */
  173.     printf ("\nConverted %d object(s), ", ObjCount);
  174.     printf ("%d light source(s).\n\n", LightOn[0] + LightOn[1] + LightOn[2]);
  175.  
  176.     printf ("  Object    Verticies   Triangles   Degen Tri \n");
  177.     printf ("---------- ----------- ----------- -----------\n");
  178.  
  179.     TotalVert = 0;
  180.     TotalTri = 0;
  181.     TotalDegen = 0;
  182.  
  183.     for (i = 0; i < ObjCount; i++) {
  184.     printf (" %-8s     %6d      %6d      %6d\n",
  185.         Names[i], Verticies[i], Triangles[i], Degens[i]);
  186.     TotalVert += Verticies[i];
  187.     TotalTri += Triangles[i];
  188.     TotalDegen += Degens[i];
  189.     }
  190.  
  191.     printf ("           =========== =========== ===========\n");
  192.     printf (" Total        %6d      %6d      %6d\n", TotalVert, TotalTri, TotalDegen);
  193.  
  194.     return 0;
  195. }
  196.  
  197.  
  198. void ProcessArgs (int argc, char *argv[])
  199. {
  200.     int i;
  201.  
  202.     printf ("         3D2 to DKB Data File Converter %s\n", Ver);
  203.     printf ("             Copyright 1991 Steve Anger\n\n");
  204.  
  205.     if (argc < 2) {
  206.     printf ("Usage: 3d2-dkb inputfile [outputfile] [[-/]options]\n\n");
  207.     printf ("Options: -d     - Preview object on screen.\n");
  208.     printf ("         -lxnnn - Set LOOK_AT x coord to nnn\n");
  209.     printf ("         -lynnn -  '     '    y   '   '   ' \n");
  210.     printf ("         -lznnn -  '     '    z   '   '   ' \n");
  211.     printf ("         -vxnnn - Set VIEW_POINT x coord to nnn\n");
  212.     printf ("         -vynnn -  '       '     y   '   '   ' \n");
  213.     printf ("         -vznnn -  '       '     z   '   '   ' \n");
  214.     printf ("         -snnn  - Smooth triangle boundaries with angles < nnn\n");
  215.     exit(1);
  216.     }
  217.  
  218.     InFile[0] = '\0';
  219.     OutFile[0] = '\0';
  220.     Display = false;
  221.  
  222.     VectInit (&LookAt, 0.0, 0.0, 0.0);
  223.     VectInit (&ViewPoint, 50.0, 50.0, -50.0);
  224.  
  225.     Smooth = 0.0;
  226.  
  227.     for (i = 1; i < argc; i++) {
  228.     if (argv[i][0] == '-' || argv[i][0] == '/') {
  229.         switch (argv[i][1]) {
  230.         case 'd': Display = true;
  231.               break;
  232.  
  233.         case 's': sscanf (&argv[i][2], "%f", &Smooth);
  234.               break;
  235.  
  236.         case 'l': switch (argv[i][2]) {
  237.                 case 'x': sscanf (&argv[i][3], "%f", &LookAt.x);
  238.                       break;
  239.                 case 'y': sscanf (&argv[i][3], "%f", &LookAt.y);
  240.                       break;
  241.                 case 'z': sscanf (&argv[i][3], "%f", &LookAt.z);
  242.               }
  243.               break;
  244.  
  245.         case 'v': switch (argv[i][2]) {
  246.                 case 'x': sscanf (&argv[i][3], "%f", &ViewPoint.x);
  247.                       break;
  248.                 case 'y': sscanf (&argv[i][3], "%f", &ViewPoint.y);
  249.                       break;
  250.                 case 'z': sscanf (&argv[i][3], "%f", &ViewPoint.z);
  251.               }
  252.         }
  253.     }
  254.     else if (InFile[0] == '\0') {
  255.         strcpy (InFile, argv[i]);
  256.         AddExt (InFile, "3D2", false);
  257.     }
  258.     else if (OutFile[0] == '\0') {
  259.         strcpy (OutFile, argv[i]);
  260.         AddExt (OutFile, "DAT", false);
  261.     }
  262.     else
  263.         Abort ("Too many file names.", 1);
  264.     }
  265.  
  266.     /* Prevent a division by zero error later on */
  267.     if ((ViewPoint.x - LookAt.x) == 0.0 && (ViewPoint.z - LookAt.z) == 0.0)
  268.     ViewPoint.z -= 0.01;
  269.  
  270.     if (OutFile[0] == '\0') {
  271.     strcpy (OutFile, InFile);
  272.     AddExt (OutFile, "DAT", true);
  273.     }
  274.  
  275.     f = fopen (InFile, "rb");
  276.     if (f == NULL)
  277.     Abort ("Error opening input file.", 2);
  278.  
  279.     g = fopen (OutFile, "w");
  280.     if (g == NULL)
  281.     Abort ("Error opening output file.", 2);
  282. }
  283.  
  284.  
  285. void AddExt (char *FileName, char *Ext, boolean Force)
  286. {
  287.     int i;
  288.  
  289.     for (i = 0; i < strlen(FileName); i++)
  290.     if (FileName[i] == '.') break;
  291.  
  292.     if (FileName[i] == '\0' || Force) {
  293.     FileName[i] = '.';
  294.     strcpy (&FileName[i+1], Ext);
  295.     }
  296. }
  297.  
  298.  
  299. byte ReadByte(FILE *f)
  300. {
  301.     return fgetc(f);
  302. }
  303.  
  304.  
  305. word ReadWord(FILE *f)
  306. {
  307.     byte bh, bl;
  308.  
  309.     bh = fgetc(f);  /* Read a Motorola format word */
  310.     bl = fgetc(f);
  311.  
  312.     return (256*bh + bl);
  313. }
  314.  
  315.  
  316. void Abort (char *Msg, int ExitCode)
  317. {
  318.     if (Display)
  319.     CloseDisplay();
  320.  
  321.     puts (Msg);
  322.     exit (ExitCode);
  323. }
  324.  
  325.  
  326. void PrintVector (FILE *g, Vector *V)
  327. {
  328.     fprintf (g, "<%.2f %.2f %.2f> ", V->x, V->y, V->z);
  329. }
  330.  
  331.  
  332. void MinVector (Vector *V1, Vector *V2)
  333. {
  334.     V1->x = (V1->x < V2->x) ? V1->x : V2->x;
  335.     V1->y = (V1->y < V2->y) ? V1->y : V2->y;
  336.     V1->z = (V1->z < V2->z) ? V1->z : V2->z;
  337. }
  338.  
  339.  
  340. void MaxVector (Vector *V1, Vector *V2)
  341. {
  342.     V1->x = (V1->x > V2->x) ? V1->x : V2->x;
  343.     V1->y = (V1->y > V2->y) ? V1->y : V2->y;
  344.     V1->z = (V1->z > V2->z) ? V1->z : V2->z;
  345. }
  346.  
  347.  
  348. int Degenerate (Triangle *Tri)
  349. {
  350.     Vector a, b, c;
  351.     Vector ab, bc, Temp;
  352.  
  353.     VectCopy (&a, &Vert[Tri->VertA]);
  354.     VectCopy (&b, &Vert[Tri->VertB]);
  355.     VectCopy (&c, &Vert[Tri->VertC]);
  356.  
  357.     VectSub (&ab, &a, &b);
  358.     VectSub (&bc, &b, &c);
  359.     CrossProd (&Temp, &ab, &bc);
  360.  
  361.     return (VectMag(&Temp) == 0.0);
  362. }
  363.  
  364.  
  365. void Read3D2Header()
  366. {
  367.     int i;
  368.     word Temp;
  369.  
  370.     if (ReadWord(f) != 0x3D02)
  371.     Abort ("Input file is not 3D2 format.", 3);
  372.  
  373.     ObjCount = ReadWord(f);
  374.  
  375.     LightOn[0] = ReadWord(f);
  376.     LightOn[1] = ReadWord(f);
  377.     LightOn[2] = ReadWord(f);
  378.  
  379.     LightBright[0] = ReadWord(f)/7.0;
  380.     LightBright[1] = ReadWord(f)/7.0;
  381.     LightBright[2] = ReadWord(f)/7.0;
  382.  
  383.     Ambient = ReadWord(f)/7.0;
  384.  
  385.     LightPos[0].y = (float)ReadWord(f);
  386.     LightPos[1].y = (float)ReadWord(f);
  387.     LightPos[2].y = (float)ReadWord(f);
  388.  
  389.     LightPos[0].z = (float)ReadWord(f);
  390.     LightPos[1].z = (float)ReadWord(f);
  391.     LightPos[2].z = (float)ReadWord(f);
  392.  
  393.     LightPos[0].x = (float)ReadWord(f);
  394.     LightPos[1].x = (float)ReadWord(f);
  395.     LightPos[2].x = (float)ReadWord(f);
  396.  
  397.     for (i = 0; i < 16; i++) {
  398.     Temp = ReadWord(f);
  399.     Pal[i].Red   = ((Temp & 0x0700) >> 8)/7.0;
  400.     Pal[i].Green = ((Temp & 0x0070) >> 4)/7.0;
  401.     Pal[i].Blue  = (Temp & 0x0007)/7.0;
  402.     }
  403.  
  404.     for (i = 0; i < 16; i++)
  405.     GBase[i] = ReadWord(f);
  406.  
  407.     PalType = ReadWord(f);
  408.     WColour = ReadWord(f);
  409.     OColour = ReadWord(f);
  410.  
  411.     for (i = 0; i < 150; i++)
  412.     ReadByte(f);
  413. }
  414.  
  415.  
  416. void Read3D2Object()
  417. {
  418.     int i;
  419.  
  420.     for (i = 0; i < 9; i++)
  421.     ObjName[i] = ReadByte(f);
  422.  
  423.     VertCount = ReadWord(f);
  424.  
  425.     Vert = malloc (VertCount * sizeof(*Vert));
  426.     if (Vert == NULL)
  427.     Abort ("Insufficient memory for verticies.", 4);
  428.  
  429.     for (i = 0; i < VertCount; i++) {
  430.     Vert[i].x = ReadWord(f)/100.0;
  431.     Vert[i].z = ReadWord(f)/100.0;
  432.     Vert[i].y = ReadWord(f)/100.0;
  433.     }
  434.  
  435.     TriCount = ReadWord(f);
  436.  
  437.     Tri = malloc (TriCount * sizeof(*Tri));
  438.     if (Tri == NULL)
  439.     Abort ("Insufficient memory for triangles.", 4);
  440.  
  441.     for (i = 0; i < TriCount; i++) {
  442.     Tri[i].VertA    = ReadWord(f);
  443.     Tri[i].VertB    = ReadWord(f);
  444.     Tri[i].VertC    = ReadWord(f);
  445.     Tri[i].EdgeFlag = ReadByte(f);
  446.     Tri[i].Colour   = ReadByte(f);
  447.     }
  448. }
  449.  
  450.  
  451. void WriteDKBHeader()
  452. {
  453.     fprintf (g, "{ Converted from file %s with 3D2-DKB %s }\n\n", InFile, Ver);
  454.     fprintf (g, "DECLARE DefaultTexture = TEXTURE\n");
  455.     fprintf (g, "    AMBIENT %.3f\n", Ambient);
  456.     fprintf (g, "    DIFFUSE 0.7\n");
  457.     fprintf (g, "END_TEXTURE\n\n");
  458.     fprintf (g, "COMPOSITE\n");
  459. }
  460.  
  461.  
  462. void BuildTriIndex()
  463. {
  464.     int Vert, i;
  465.     TriangleNode *Temp;
  466.  
  467.     /* Build a table containing a list of the triangles that use */
  468.     /* each vertex (ie. TriList[n] = List of triangles touching vertex n) */
  469.     TriList = malloc (VertCount * sizeof(TriList));
  470.     if (TriList == NULL)
  471.     Abort ("Insufficient memory for smooth triangles.", 4);
  472.  
  473.     for (i = 0; i < VertCount; i++)
  474.     TriList[i] = NULL;
  475.  
  476.     for (i = 0; i < TriCount; i++) {
  477.     Vert = Tri[i].VertA;
  478.     Temp = TriList[Vert];
  479.     TriList[Vert] = malloc (sizeof (*TriList));
  480.     if (TriList[Vert] == NULL)
  481.         Abort ("Insufficient memory for smooth triangles.", 4);
  482.     TriList[Vert]->TriNo = i;
  483.     TriList[Vert]->Next = Temp;
  484.  
  485.     Vert = Tri[i].VertB;
  486.     Temp = TriList[Vert];
  487.     TriList[Vert] = malloc (sizeof (*TriList));
  488.     if (TriList[Vert] == NULL)
  489.         Abort ("Insufficient memory for smooth triangles.", 4);
  490.     TriList[Vert]->TriNo = i;
  491.     TriList[Vert]->Next = Temp;
  492.  
  493.     Vert = Tri[i].VertC;
  494.     Temp = TriList[Vert];
  495.     TriList[Vert] = malloc (sizeof (*TriList));
  496.     if (TriList[Vert] == NULL)
  497.         Abort ("Insufficient memory for smooth triangles.", 4);
  498.     TriList[Vert]->TriNo = i;
  499.     TriList[Vert]->Next = Temp;
  500.     }
  501. }
  502.  
  503.  
  504. void DumpTriIndex()
  505. {
  506.     int i;
  507.  
  508.     for (i = 0; i < VertCount; i++)
  509.     free (TriList[i]);
  510.  
  511.     free (TriList);
  512. }
  513.  
  514.  
  515. void VertNormal (Triangle *T, Vector *NormA, Vector *NormB, Vector *NormC)
  516. {
  517.     TriangleNode  *p;
  518.     Vector  Normal, CurrNorm;
  519.  
  520.     VectInit (NormA, 0.0, 0.0, 0.0);
  521.     VectInit (NormB, 0.0, 0.0, 0.0);
  522.     VectInit (NormC, 0.0, 0.0, 0.0);
  523.  
  524.     TriNormal (T, &CurrNorm);
  525.  
  526.     for (p = TriList[T->VertA]; p != NULL; p = p->Next) {
  527.     TriNormal (&Tri[p->TriNo], &Normal);
  528.     if (VectAngle (&CurrNorm, &Normal) < Smooth)
  529.         VectAdd (NormA, NormA, &Normal);
  530.     }
  531.  
  532.     for (p = TriList[T->VertB]; p != NULL; p = p->Next) {
  533.     TriNormal (&Tri[p->TriNo], &Normal);
  534.     if (VectAngle (&CurrNorm, &Normal) < Smooth)
  535.         VectAdd (NormB, NormB, &Normal);
  536.     }
  537.  
  538.     for (p = TriList[T->VertC]; p != NULL; p = p->Next) {
  539.     TriNormal (&Tri[p->TriNo], &Normal);
  540.     if (VectAngle (&CurrNorm, &Normal) < Smooth)
  541.         VectAdd (NormC, NormC, &Normal);
  542.     }
  543.  
  544.     VectScale (NormA, 1.0/VectMag (NormA));
  545.     VectScale (NormB, 1.0/VectMag (NormB));
  546.     VectScale (NormC, 1.0/VectMag (NormC));
  547. }
  548.  
  549.  
  550. void TriNormal (Triangle *T, Vector *Normal)
  551. {
  552.     Vector AB, AC;
  553.     float Mag;
  554.  
  555.     VectSub (&AB, &Vert[T->VertB], &Vert[T->VertA]);
  556.     VectSub (&AC, &Vert[T->VertC], &Vert[T->VertA]);
  557.     CrossProd (Normal, &AC, &AB);
  558.  
  559.     Mag = VectMag (Normal);
  560.     if (Mag > 0.0)
  561.     VectScale (Normal, 1.0/Mag);
  562.     else
  563.     VectInit (Normal, 0.0, 0.0, 0.0);
  564. }
  565.  
  566.  
  567. void WriteDKBObject()
  568. {
  569.     int i, j;
  570.     boolean Start;
  571.     Vector NormA, NormB, NormC;
  572.  
  573.     if (Smooth > 0.0)
  574.     BuildTriIndex();
  575.  
  576.     DegenTri = 0;
  577.  
  578.     for (i = 0; i < 16; i++) {
  579.     Start = false;
  580.     VectInit (&ObjMin, +1e8, +1e8, +1e8);
  581.     VectInit (&ObjMax, -1e8, -1e8, -1e8);
  582.  
  583.     for (j = 0; j < TriCount; j++) {
  584.         if (Tri[j].Colour == i) {
  585.         if (!Start) {
  586.             Start = true;
  587.             fprintf (g, "    OBJECT {%s, Pal #%d}\n", ObjName, i);
  588.             fprintf (g, "        UNION\n");
  589.         }
  590.  
  591.         if (Degenerate (&Tri[j]))
  592.             ++DegenTri;  /* Exclude degenerate triangles */
  593.         else {
  594.             if (Smooth > 0.0) {
  595.             /* Compute vertex normals for smooth triangle */
  596.             VertNormal (&Tri[j], &NormA, &NormB, &NormC);
  597.  
  598.             fprintf (g, "            SMOOTH_TRIANGLE ");
  599.             PrintVector (g, &Vert[Tri[j].VertA]);
  600.             PrintVector (g, &NormA);
  601.             PrintVector (g, &Vert[Tri[j].VertB]);
  602.             PrintVector (g, &NormB);
  603.             PrintVector (g, &Vert[Tri[j].VertC]);
  604.             PrintVector (g, &NormC);
  605.             fprintf (g, "END_TRIANGLE\n");
  606.             }
  607.             else {
  608.             fprintf (g, "            TRIANGLE ");
  609.             PrintVector (g, &Vert[Tri[j].VertA]);
  610.             PrintVector (g, &Vert[Tri[j].VertB]);
  611.             PrintVector (g, &Vert[Tri[j].VertC]);
  612.             fprintf (g, "END_TRIANGLE\n");
  613.             }
  614.  
  615.             MinVector (&ObjMin, &Vert[Tri[j].VertA]);
  616.             MinVector (&ObjMin, &Vert[Tri[j].VertB]);
  617.             MinVector (&ObjMin, &Vert[Tri[j].VertC]);
  618.  
  619.             MaxVector (&ObjMax, &Vert[Tri[j].VertA]);
  620.             MaxVector (&ObjMax, &Vert[Tri[j].VertB]);
  621.             MaxVector (&ObjMax, &Vert[Tri[j].VertC]);
  622.  
  623.             if (Display)
  624.             PlotTriangle (&Tri[j]);
  625.         }
  626.         }
  627.     }
  628.  
  629.     if (Start) {
  630.         fprintf (g, "        END_UNION\n\n");
  631.  
  632.         fprintf (g, "        BOUNDED_BY\n");
  633.         fprintf (g, "            INTERSECTION\n");
  634.         fprintf (g, "                PLANE <+1.0 0.0 0.0> %.2f END_PLANE\n", +ObjMax.x);
  635.         fprintf (g, "                PLANE <-1.0 0.0 0.0> %.2f END_PLANE\n", -ObjMin.x);
  636.         fprintf (g, "                PLANE <0.0 +1.0 0.0> %.2f END_PLANE\n", +ObjMax.y);
  637.         fprintf (g, "                PLANE <0.0 -1.0 0.0> %.2f END_PLANE\n", -ObjMin.y);
  638.         fprintf (g, "                PLANE <0.0 0.0 +1.0> %.2f END_PLANE\n", +ObjMax.z);
  639.         fprintf (g, "                PLANE <0.0 0.0 -1.0> %.2f END_PLANE\n", -ObjMin.z);
  640.         fprintf (g, "            END_INTERSECTION\n");
  641.         fprintf (g, "        END_BOUND\n\n");
  642.  
  643.         fprintf (g, "        TEXTURE\n");
  644.         fprintf (g, "            DefaultTexture\n");
  645.         fprintf (g, "            COLOUR RED %.3f GREEN %.3f BLUE %.3f\n",
  646.                      Pal[i].Red, Pal[i].Green, Pal[i].Blue);
  647.         fprintf (g, "        END_TEXTURE\n");
  648.         fprintf (g, "        COLOUR RED %.3f GREEN %.3f BLUE %.3f\n",
  649.                  Pal[i].Red, Pal[i].Green, Pal[i].Blue);
  650.  
  651.         fprintf (g, "    END_OBJECT {%s, Pal #%d}\n\n", ObjName, i);
  652.     }
  653.     }
  654.  
  655.     if (Smooth > 0.0)
  656.     DumpTriIndex();
  657.  
  658.     free (Vert);    /* Free memory used by vertex/triangle lists */
  659.     free (Tri);
  660. }
  661.  
  662.  
  663. void WriteDKBSummary()
  664. {
  665.     Vector Sky, Right, Direction;
  666.     int i;
  667.  
  668.     fprintf (g, "END_COMPOSITE\n\n");
  669.  
  670.     for (i = 0; i < 3; i++) {
  671.     if (LightOn[i]) {
  672.         fprintf (g, "OBJECT\n");
  673.         fprintf (g, "    SPHERE <0.0 0.0 0.0> 1.0 END_SPHERE\n");
  674.         fprintf (g, "    TRANSLATE <%.2f %.2f %.2f>\n", LightPos[i].x, LightPos[i].y, LightPos[i].z);
  675.         fprintf (g, "    TEXTURE\n");
  676.         fprintf (g, "        COLOUR RED %.3f GREEN %.3f BLUE %.3f\n",
  677.                  LightBright[i], LightBright[i], LightBright[i]);
  678.         fprintf (g, "        DIFFUSE 0.0\n");
  679.         fprintf (g, "        AMBIENT 1.0\n");
  680.         fprintf (g, "    END_TEXTURE\n");
  681.         fprintf (g, "    LIGHT_SOURCE\n");
  682.         fprintf (g, "    COLOUR RED %.3f GREEN %.3f BLUE %.3f\n",
  683.                  LightBright[i], LightBright[i], LightBright[i]);
  684.         fprintf (g, "END_OBJECT\n\n");
  685.     }
  686.     }
  687.  
  688.     VectInit (&Sky, 0.0, 1.0, 0.0);
  689.     VectSub (&Direction, &LookAt, &ViewPoint);
  690.     CrossProd (&Right, &Sky, &Direction);
  691.     VectScale (&Right, 1.33333/VectMag(&Right));
  692.  
  693.     fprintf (g, "VIEW_POINT\n");
  694.     fprintf (g, "    LOCATION "); PrintVector (g, &ViewPoint); fprintf (g, "\n");
  695.     fprintf (g, "    LOOK_AT "); PrintVector (g, &LookAt); fprintf (g, "\n");
  696.     fprintf (g, "    SKY "); PrintVector (g, &Sky); fprintf (g, "\n");
  697.     fprintf (g, "    RIGHT "); PrintVector (g, &Right); fprintf (g, "\n");
  698.     fprintf (g, "END_VIEW_POINT\n\n");
  699. }
  700.  
  701.  
  702.  
  703. void VectAdd (Vector *V1, Vector *V2, Vector *V3)
  704. {
  705.     V1->x = V2->x + V3->x;
  706.     V1->y = V2->y + V3->y;
  707.     V1->z = V2->z + V3->z;
  708. }
  709.  
  710.  
  711. void VectSub (Vector *V1, Vector *V2, Vector *V3)
  712. {
  713.     V1->x = V2->x - V3->x;
  714.     V1->y = V2->y - V3->y;
  715.     V1->z = V2->z - V3->z;
  716. }
  717.  
  718.  
  719. void VectScale (Vector *V, float k)
  720. {
  721.     V->x = k*V->x;
  722.     V->y = k*V->y;
  723.     V->z = k*V->z;
  724. }
  725.  
  726.  
  727. float VectMag (Vector *V)
  728. {
  729.     return sqrt((V->x * V->x) + (V->y * V->y) + (V->z * V->z));
  730. }
  731.  
  732.  
  733. float DotProd (Vector *V1, Vector *V2)
  734. {
  735.     return (V1->x*V2->x + V1->y*V2->y + V1->z*V2->z);
  736. }
  737.  
  738.  
  739. void CrossProd (Vector *V1, Vector *V2, Vector *V3)
  740. {
  741.     V1->x = (V2->y * V3->z) - (V2->z * V3->y);
  742.     V1->y = (V2->z * V3->x) - (V2->x * V3->z);
  743.     V1->z = (V2->x * V3->y) - (V2->y * V3->x);
  744. }
  745.  
  746.  
  747. void VectCopy (Vector *V1, Vector *V2)
  748. {
  749.     V1->x = V2->x;
  750.     V1->y = V2->y;
  751.     V1->z = V2->z;
  752. }
  753.  
  754.  
  755. void VectInit (Vector *V, float x, float y, float z)
  756. {
  757.     V->x = x;
  758.     V->y = y;
  759.     V->z = z;
  760. }
  761.  
  762.  
  763. float VectAngle (Vector *V1, Vector *V2)
  764. {
  765.     float Mag1, Mag2, Angle;
  766.  
  767.     Mag1 = VectMag(V1);
  768.     Mag2 = VectMag(V2);
  769.  
  770.     if (Mag1 > 0.0 && Mag2 > 0.0)
  771.     Angle = (180.0/M_PI) * acos(min(1.0, DotProd(V1,V2)/(Mag1 * Mag2)));
  772.     else
  773.     Angle = 0.0;
  774.  
  775.  
  776.     return Angle;
  777. }
  778.  
  779.  
  780. void InitDisplay()
  781. {
  782. #ifdef __TURBOC__
  783.     int graphdriver = DETECT, graphmode;
  784.  
  785.     Vector Temp;
  786.  
  787.     VectSub (&Nz, &LookAt, &ViewPoint);
  788.     VectScale (&Nz, 1.0/VectMag(&Nz));
  789.  
  790.     VectCopy (&Temp, &Nz);
  791.     VectScale (&Temp, Nz.y/DotProd(&Nz, &Nz));
  792.     VectInit (&Ny, 0.0, 1.0, 0.0);
  793.     VectSub (&Ny, &Ny, &Temp);
  794.     VectScale (&Ny, 1.0/VectMag(&Ny));
  795.  
  796.     CrossProd (&Nx, &Ny, &Nz);
  797.  
  798.     if (Display) {
  799.     initgraph (&graphdriver, &graphmode, "");
  800.     if (graphresult() != grOk) {
  801.         printf ("Error initializing graphics display.\n");
  802.         Display = false;
  803.     }
  804.     }
  805. #endif
  806. }
  807.  
  808.  
  809. void PlotTriangle (Triangle *Tr)
  810. {
  811. #ifdef __TURBOC__
  812.     Vector a, b, c, T;
  813.     int ax, ay, bx, by, cx, cy, Shade;
  814.     float rd, gr, bl;
  815.  
  816.     VectCopy (&a, &Vert[Tr->VertA]);
  817.     VectCopy (&b, &Vert[Tr->VertB]);
  818.     VectCopy (&c, &Vert[Tr->VertC]);
  819.  
  820.     VectSub (&a, &a, &ViewPoint);
  821.     T.x = DotProd (&a, &Nx);
  822.     T.y = DotProd (&a, &Ny);
  823.     T.z = DotProd (&a, &Nz);
  824.     VectCopy (&a, &T);
  825.  
  826.     VectSub (&b, &b, &ViewPoint);
  827.     T.x = DotProd (&b, &Nx);
  828.     T.y = DotProd (&b, &Ny);
  829.     T.z = DotProd (&b, &Nz);
  830.     VectCopy (&b, &T);
  831.  
  832.     VectSub (&c, &c, &ViewPoint);
  833.     T.x = DotProd (&c, &Nx);
  834.     T.y = DotProd (&c, &Ny);
  835.     T.z = DotProd (&c, &Nz);
  836.     VectCopy (&c, &T);
  837.  
  838.     /* Don't plot anything that's behind you */
  839.     if (a.z <= 0.0 || b.z <= 0.0 || c.z <= 0.0)
  840.     return;
  841.  
  842.     ax = (0.75*a.x/a.z + 0.5)*getmaxx();
  843.     bx = (0.75*b.x/b.z + 0.5)*getmaxx();
  844.     cx = (0.75*c.x/c.z + 0.5)*getmaxx();
  845.     ay = (0.5 - a.y/a.z)*getmaxy();
  846.     by = (0.5 - b.y/b.z)*getmaxy();
  847.     cy = (0.5 - c.y/c.z)*getmaxy();
  848.  
  849.     Shade = 0;
  850.     bl = Pal[Tr->Colour].Blue;
  851.     gr = Pal[Tr->Colour].Green;
  852.     rd = Pal[Tr->Colour].Red;
  853.     Shade = 1*(bl > 0.3) + 2*(gr > 0.3) + 4*(rd > 0.3) + 8*(bl+gr+rd > 1.5);
  854.  
  855.     if (Shade == 0)
  856.     Shade = 8;
  857.  
  858.     setcolor (Shade);
  859.  
  860.     moveto (ax, ay);
  861.     lineto (bx, by);
  862.     lineto (cx, cy);
  863.     lineto (ax, ay);
  864. #endif
  865. }
  866.  
  867.  
  868. void CloseDisplay()
  869. {
  870. #ifdef __TURBOC__
  871.     printf ("Conversion complete.\nPress any key.");
  872.     getch();
  873.     closegraph();
  874. #endif
  875. }
  876.  
  877.